home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / LANG / ADA / GNAT / !gcc / adainc / 2 / adb / a-teioed < prev    next >
Text File  |  1996-02-12  |  68KB  |  1,823 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT RUNTIME COMPONENTS                          --
  4. --                                                                          --
  5. --                  A D A . T E X T _ I O . E D I T I N G                   --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.6 $                              --
  10. --                                                                          --
  11. -- GNAT is free software;  you can  redistribute it  and/or modify it under --
  12. -- terms of the  GNU General Public License as published  by the Free Soft- --
  13. -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
  14. -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
  15. -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  16. -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
  17. -- for  more details.  You should have  received  a copy of the GNU General --
  18. -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
  19. -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
  20. -- MA 02111-1307, USA.                                                      --
  21. --                                                                          --
  22. -- As a special exception,  if other files  instantiate  generics from this --
  23. -- unit, or you link  this unit with other files  to produce an executable, --
  24. -- this  unit  does not  by itself cause  the resulting  executable  to  be --
  25. -- covered  by the  GNU  General  Public  License.  This exception does not --
  26. -- however invalidate  any other reasons why  the executable file  might be --
  27. -- covered by the  GNU Public License.                                      --
  28. --                                                                          --
  29. -- GNAT was originally developed  by the GNAT team at  New York University. --
  30. -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
  31. --                                                                          --
  32. ------------------------------------------------------------------------------
  33.  
  34.  
  35.  
  36. with Ada.Strings.Fixed;
  37.  
  38. package body Ada.Text_IO.Editing is
  39.  
  40.    function Parse_Number_String (Str : String) return Number_Attributes is
  41.       --  Changes
  42.       --    RIE 08/19/94 Fix 0.0007 as 7.0000 bug.
  43.       Answer : Number_Attributes;
  44.    begin
  45.       for I in Str'Range loop
  46.          case Str (I) is
  47.             when ' ' =>
  48.                null; --  ignore
  49.             when '1' .. '9' => --  decide if this is the start of a number.
  50.                --  if so, figure out which one...
  51.                if Answer.Has_Fraction then
  52.                   Answer.End_Of_Fraction := I;
  53.                else
  54.                   if Answer.Start_Of_Int = Invalid_Position then
  55.                      --  start integer
  56.                      Answer.Start_Of_Int := I;
  57.                   end if;
  58.                   Answer.End_Of_Int := I;
  59.                end if;
  60.             when '0' =>
  61.                if not Answer.Has_Fraction then
  62.                   if Answer.Start_Of_Int /= Invalid_Position then
  63.                      Answer.End_Of_Int := I;
  64.                   end if;
  65.                end if;
  66.                --  Only count a zero before the decimal point if it follows a
  67.                --  non-zero digit.  After the decimal point, zeros will be
  68.                --  counted if followed by a non-zero digit.
  69.             when '-' => --  set negative
  70.                Answer.Negative := True;
  71.             when '.' => --  close integer, start fraction
  72.                if Answer.Has_Fraction then
  73.                   raise Picture_Error;
  74.                end if;
  75.                --  Two decimal points is a no-no.
  76.                Answer.Has_Fraction    := True;
  77.                Answer.End_Of_Fraction := I;
  78.                --  Could leave this at Invalid_Position, but this seems the
  79.                --  right way to indicate a null range...
  80.                Answer.Start_Of_Fraction := I + 1;
  81.                Answer.End_Of_Int        := I - 1;
  82.             when others =>
  83.                raise Picture_Error; --  Never Happen?
  84.          end case;
  85.       end loop;
  86.  
  87.       if Answer.Start_Of_Int = Invalid_Position then
  88.          Answer.Start_Of_Int := Answer.End_Of_Int + 1;
  89.       end if;
  90.       --  no significant (intger) digits needs a null range.
  91.  
  92.       return Answer;
  93.  
  94.    end Parse_Number_String;
  95.  
  96.    procedure Precalculate  (Pic : in out Format_Record) is
  97.  
  98.       Computed_BWZ : Boolean := True;
  99.       Debug : Boolean := False;
  100.       --   Am I finished at Last?
  101.  
  102.       type Legality is  (Okay, Reject);
  103.       State : Legality := Reject;
  104.       --  Start in reject, which will reject null strings.
  105.  
  106.       Index : Pic_Index := Pic.Picture.Expanded'First;
  107.  
  108.       function At_End return Boolean;
  109.       procedure Set_State (L : Legality);
  110.       function Look return Character;
  111.       function Is_Insert return Boolean;
  112.       procedure Skip;
  113.       procedure Debug_Start (Name : String);
  114.       procedure Debug_Integer  (Value : in Integer; S : String);
  115.       procedure Trailing_Currency;
  116.       procedure Trailing_Bracket;
  117.       procedure Number_Fraction;
  118.       procedure Number_Completion;
  119.       procedure Number_Fraction_Or_Bracket;
  120.       procedure Number_Fraction_Or_Z_Fill;
  121.       procedure Zero_Suppression;
  122.       procedure Floating_Bracket;
  123.       procedure Number_Fraction_Or_Star_Fill;
  124.       procedure Star_Suppression;
  125.       procedure Number_Fraction_Or_Dollar;
  126.       procedure Leading_Dollar;
  127.       procedure Number_Fraction_Or_Pound;
  128.       procedure Leading_Pound;
  129.       procedure Picture;
  130.       procedure Floating_Plus;
  131.       procedure Floating_Minus;
  132.       procedure Picture_Plus;
  133.       procedure Picture_Minus;
  134.       procedure Picture_Bracket;
  135.       procedure Number;
  136.       procedure Optional_RHS_Sign;
  137.       procedure Picture_String;
  138.  
  139.  
  140.       function At_End return Boolean is
  141.       begin
  142.          return Index > Pic.Picture.Length;
  143.       end At_End;
  144.       pragma Inline  (At_End);
  145.  
  146.       procedure Set_State (L : Legality) is
  147.       begin
  148.          if Debug then
  149.             Text_IO.Put_Line ("  Set state from " & Legality'Image (State) &
  150.                              " to " & Legality'Image (L));
  151.          end if;
  152.          State := L;
  153.       end Set_State;
  154.       pragma Inline  (Set_State);
  155.  
  156.       function Look return Character is
  157.       begin
  158.          if At_End then raise Picture_Error; end if;
  159.          return Pic.Picture.Expanded (Index);
  160.       end Look;
  161.       pragma Inline  (Look);
  162.  
  163.       function Is_Insert return Boolean is
  164.       begin
  165.          if At_End then return False; end if;
  166.          case Pic.Picture.Expanded (Index) is
  167.             when '_' | '0' | '/' => return True;
  168.             when 'B' | 'b' =>
  169.                Pic.Picture.Expanded (Index) := 'b'; --  canonical
  170.                return True;
  171.             when others => return False;
  172.          end case;
  173.       end Is_Insert;
  174.       pragma Inline  (Is_Insert);
  175.  
  176.       procedure Skip is
  177.       begin
  178.          if Debug then
  179.             Text_IO.Put_Line ("  Skip " & Pic.Picture.Expanded (Index));
  180.          end if;
  181.          Index := Index + 1;
  182.       end Skip;
  183.       pragma Inline  (Skip);
  184.  
  185.       procedure Debug_Start (Name : String) is
  186.       begin
  187.          if Debug then
  188.             Text_IO.Put_Line ("  In " & Name & '.');
  189.          end if;
  190.       end Debug_Start;
  191.       pragma Inline  (Debug_Start);
  192.  
  193.       procedure Debug_Integer  (Value : in Integer; S : String) is
  194.          use Text_IO; --  needed for >
  195.       begin
  196.          if Debug and then Value > 0 then
  197.             if Text_IO.Col > 70 - S'Length then Text_IO.New_Line; end if;
  198.             Text_IO.Put (' ' & S & Integer'Image (Value) & ',');
  199.          end if;
  200.       end Debug_Integer;
  201.       pragma Inline  (Debug_Integer);
  202.  
  203.       procedure Trailing_Currency is
  204.       begin
  205.          Debug_Start ("Trailing_Currency");
  206.          if At_End then return; end if;
  207.          if Look = '$' then
  208.             Pic.Start_Currency := Index;
  209.             Pic.End_Currency := Index;
  210.             Skip;
  211.          else
  212.             while not At_End and then Look = '#' loop
  213.                if Pic.Start_Currency = Invalid_Position then
  214.                   Pic.Start_Currency := Index;
  215.                end if;
  216.                Pic.End_Currency := Index;
  217.                Skip;
  218.             end loop;
  219.          end if;
  220.          loop
  221.             if At_End then return; end if;
  222.             case Look is
  223.                when '_' | '0' | '/' => Skip;
  224.                when 'B' | 'b'  =>
  225.                   Pic.Picture.Expanded (Index) := 'b';
  226.                   Skip;
  227.                when others => return;
  228.             end case;
  229.          end loop;
  230.       end Trailing_Currency;
  231.  
  232.       procedure Trailing_Bracket is
  233.       begin
  234.          Debug_Start ("Trailing_Bracket");
  235.          if Look = '>' then
  236.             Pic.Second_Sign := Index;
  237.             Skip;
  238.          else raise Picture_Error;
  239.          end if;
  240.       end Trailing_Bracket;
  241.  
  242.       procedure Number_Fraction is
  243.          --  Note that number fraction can be called in either State.
  244.          --  It will set state to Valid only if a 9 is encountered.
  245.       begin
  246.          Debug_Start ("Number_Fraction");
  247.          loop
  248.             if At_End then return; end if;
  249.             case Look is
  250.                when '_' | '0' | '/' => Skip;
  251.                when 'B' | 'b'  =>
  252.                   Pic.Picture.Expanded (Index) := 'b';
  253.                   Skip;
  254.                when '9' =>
  255.                   Computed_BWZ := False;
  256.                   Pic.Max_Trailing_Digits := Pic.Max_Trailing_Digits + 1;
  257.                   Set_State (Okay); Skip;
  258.                when others => return;
  259.             end case;
  260.          end loop;
  261.       end Number_Fraction;
  262.  
  263.       procedure Number_Completion is
  264.       begin
  265.          Debug_Start ("Number_Completion");
  266.          while not At_End loop
  267.             case Look is
  268.                when '_' | '0' | '/' => Skip;
  269.                when 'B' | 'b'  =>
  270.                   Pic.Picture.Expanded (Index) := 'b';
  271.                   Skip;
  272.                when '9' =>
  273.                   Computed_BWZ := False;
  274.                   Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
  275.                   Set_State (Okay);
  276.                   Skip;
  277.                when 'V' | 'v' | '.' =>
  278.                   Pic.Radix_Position := Index;
  279.                   Skip;
  280.                   Number_Fraction;
  281.                   return;
  282.                when others => return;
  283.             end case;
  284.          end loop;
  285.       end Number_Completion;
  286.  
  287.       procedure Number_Fraction_Or_Bracket is
  288.       begin
  289.          Debug_Start ("Number_Fraction_Or_Bracket");
  290.          loop
  291.             if At_End then return; end if;
  292.             case Look is
  293.                when '_' | '0' | '/' => Skip;
  294.                when 'B' | 'b'  =>
  295.                   Pic.Picture.Expanded (Index) := 'b';
  296.                   Skip;
  297.                when '<' =>
  298.                   Pic.Max_Trailing_Digits := Pic.Max_Trailing_Digits + 1;
  299.                   Pic.End_Float := Index;
  300.                   Skip;
  301.                   loop
  302.                      if At_End then return; end if;
  303.                      case Look is
  304.                         when '_' | '0' | '/' => Skip;
  305.                         when 'B' | 'b'  =>
  306.                            Pic.Picture.Expanded (Index) := 'b';
  307.                            Skip;
  308.                         when '<' =>
  309.                            Pic.Max_Trailing_Digits :=
  310.                               Pic.Max_Trailing_Digits + 1;
  311.                            Pic.End_Float := Index;
  312.                            Skip;
  313.                         when others => return;
  314.                      end case;
  315.                   end loop;
  316.                when others => Number_Fraction; return;
  317.             end case;
  318.          end loop;
  319.       end Number_Fraction_Or_Bracket;
  320.  
  321.       procedure Number_Fraction_Or_Z_Fill is
  322.       begin
  323.          Debug_Start ("Number_Fraction_Or_Z_Fill");
  324.          loop
  325.             if At_End then return; end if;
  326.             case Look is
  327.                when '_' | '0' | '/' => Skip;
  328.                when 'B' | 'b'  =>
  329.                   Pic.Picture.Expanded (Index) := 'b';
  330.                   Skip;
  331.                when 'Z' | 'z' =>
  332.                   Pic.Max_Trailing_Digits := Pic.Max_Trailing_Digits + 1;
  333.                   Pic.End_Float := Index;
  334.                   Pic.Picture.Expanded (Index) := 'Z';
  335.                   --  consistancy
  336.                   Skip;
  337.                   loop
  338.                      if At_End then return; end if;
  339.                      case Look is
  340.                         when '_' | '0' | '/' => Skip;
  341.                         when 'B' | 'b'  =>
  342.                            Pic.Picture.Expanded (Index) := 'b';
  343.                            Skip;
  344.                         when 'Z' | 'z' =>
  345.                            Pic.Picture.Expanded (Index) := 'Z';
  346.                            --  consistancy
  347.                            Pic.Max_Trailing_Digits :=
  348.                               Pic.Max_Trailing_Digits + 1;
  349.                            Pic.End_Float := Index;
  350.                            Skip;
  351.                         when others => return;
  352.                      end case;
  353.                   end loop;
  354.                when others => Number_Fraction; return;
  355.             end case;
  356.          end loop;
  357.       end Number_Fraction_Or_Z_Fill;
  358.  
  359.       procedure Zero_Suppression is
  360.       begin
  361.          Debug_Start ("Zero_Suppression");
  362.          Pic.Floater := 'Z';
  363.          Pic.Start_Float := Index;
  364.          Pic.End_Float := Index;
  365.          Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
  366.          Pic.Picture.Expanded (Index) := 'Z';
  367.          --  consistancy
  368.          Skip; --  Known Z
  369.          loop
  370.             if At_End then Set_State (Okay); return; end if;
  371.             --  even a single Z is a valid picture
  372.             case Look is
  373.                when '_' | '0' | '/' =>
  374.                   Pic.End_Float := Index;
  375.                   Skip;
  376.                when 'B' | 'b'  =>
  377.                   Pic.End_Float := Index;
  378.                   Pic.Picture.Expanded (Index) := 'b';
  379.                   Skip;
  380.                when 'Z' | 'z' =>
  381.                   Pic.Picture.Expanded (Index) := 'Z';
  382.                   --  consistancy
  383.                   Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
  384.                   Pic.End_Float := Index;
  385.                   Set_State (Okay);
  386.                   Skip;
  387.                when '9' =>
  388.                   Set_State (Okay);
  389.                   Number_Completion;
  390.                   return;
  391.                when '.' | 'V' | 'v' =>
  392.                   Pic.Radix_Position := Index;
  393.                   Skip; Number_Fraction_Or_Z_Fill; return;
  394.                when '#' | '$' => Trailing_Currency; Set_State (Okay); return;
  395.                when others => raise Picture_Error;
  396.             end case;
  397.          end loop;
  398.       end Zero_Suppression;
  399.  
  400.       procedure Floating_Bracket is
  401.          --  Note that Floating_Bracket is only called with an acceptable
  402.          --  prefix. But we don't set Okay, because we must end with a '>'.
  403.       begin
  404.          Debug_Start ("Floating_Bracket");
  405.          Pic.Floater := '<';
  406.          Pic.End_Float := Index;
  407.          Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
  408.          --  First bracket wasn't counted...
  409.          Skip; --  known '<'
  410.          loop
  411.             if At_End then return; end if;
  412.             case Look is
  413.                when '_' | '0' | '/' =>
  414.                   Pic.End_Float := Index;
  415.                   Skip;
  416.                when 'B' | 'b'  =>
  417.                   Pic.End_Float := Index;
  418.                   Pic.Picture.Expanded (Index) := 'b';
  419.                   Skip;
  420.                when '<' =>
  421.                   Pic.End_Float := Index;
  422.                   Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
  423.                   Skip;
  424.                when '9' =>
  425.                   Number_Completion;
  426.                when 'V' | 'v' | '.' =>
  427.                   Pic.Radix_Position := Index;
  428.                   Skip; Number_Fraction_Or_Bracket; return;
  429.                when others => return;
  430.             end case;
  431.          end loop;
  432.       end Floating_Bracket;
  433.  
  434.       procedure Number_Fraction_Or_Star_Fill is
  435.       begin
  436.          Debug_Start ("Number_Fraction_Or_Star_Fill");
  437.          loop
  438.             if At_End then return; end if;
  439.             case Look is
  440.                when '_' | '0' | '/' => Skip;
  441.                when 'B' | 'b'  =>
  442.                   Pic.Picture.Expanded (Index) := 'b';
  443.                   Skip;
  444.                when '*' =>
  445.                   Pic.Star_Fill := True;
  446.                   Pic.Max_Trailing_Digits := Pic.Max_Trailing_Digits + 1;
  447.                   Pic.End_Float := Index;
  448.                   Skip;
  449.                   loop
  450.                      if At_End then return; end if;
  451.                      case Look is
  452.                         when '_' | '0' | '/' => Skip;
  453.                         when 'B' | 'b'  =>
  454.                            Pic.Picture.Expanded (Index) := 'b';
  455.                            Skip;
  456.                         when '*' =>
  457.                            Pic.Star_Fill := True;
  458.                            Pic.Max_Trailing_Digits :=
  459.                               Pic.Max_Trailing_Digits + 1;
  460.                            Pic.End_Float := Index;
  461.                            Skip;
  462.                         when others => return;
  463.                      end case;
  464.                   end loop;
  465.                when others => Number_Fraction; return;
  466.             end case;
  467.          end loop;
  468.       end Number_Fraction_Or_Star_Fill;
  469.  
  470.       procedure Star_Suppression is
  471.       begin
  472.          Debug_Start ("Star_Suppression");
  473.          Pic.Floater := '*';
  474.          Pic.Start_Float := Index;
  475.          Pic.End_Float := Index;
  476.          Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
  477.          Set_State (Okay);
  478.          --  even a single * is a valid picture
  479.          Pic.Star_Fill := True;
  480.          Skip; --  Known *
  481.          loop
  482.             if At_End then return; end if;
  483.             case Look is
  484.                when '_' | '0' | '/' =>
  485.                   Pic.End_Float := Index;
  486.                   Skip;
  487.                when 'B' | 'b'  =>
  488.                   Pic.End_Float := Index;
  489.                   Pic.Picture.Expanded (Index) := 'b';
  490.                   Skip;
  491.                when '*' =>
  492.                   Pic.End_Float := Index;
  493.                   Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
  494.                   Set_State (Okay); Skip;
  495.                when '9' => Set_State (Okay); Number_Completion; return;
  496.                when '.' | 'V' | 'v' =>
  497.                   Pic.Radix_Position := Index;
  498.                   Skip; Number_Fraction_Or_Star_Fill; return;
  499.                when '#' | '$' => Trailing_Currency; Set_State (Okay); return;
  500.                when others => raise Picture_Error;
  501.             end case;
  502.          end loop;
  503.       end Star_Suppression;
  504.  
  505.       procedure Number_Fraction_Or_Dollar is
  506.       begin
  507.          Debug_Start ("Number_Fraction_Or_Dollar");
  508.          loop
  509.             if At_End then return; end if;
  510.             case Look is
  511.                when '_' | '0' | '/' => Skip;
  512.                when 'B' | 'b'  =>
  513.                   Pic.Picture.Expanded (Index) := 'b';
  514.                   Skip;
  515.                when '$' =>
  516.                   Pic.Max_Trailing_Digits := Pic.Max_Trailing_Digits + 1;
  517.                   Pic.End_Float := Index;
  518.                   Skip;
  519.                   loop
  520.                      if At_End then return; end if;
  521.                      case Look is
  522.                         when '_' | '0' | '/' => Skip;
  523.                         when 'B' | 'b'  =>
  524.                            Pic.Picture.Expanded (Index) := 'b';
  525.                            Skip;
  526.                         when '$' =>
  527.                            Pic.Max_Trailing_Digits :=
  528.                               Pic.Max_Trailing_Digits + 1;
  529.                            Pic.End_Float := Index;
  530.                            Skip;
  531.                         when others => return;
  532.                      end case;
  533.                   end loop;
  534.                when others => Number_Fraction; return;
  535.             end case;
  536.          end loop;
  537.       end Number_Fraction_Or_Dollar;
  538.  
  539.       procedure Leading_Dollar is
  540.          --  Note that Leading_Dollar can be called in either State.
  541.          --  It will set state to Okay only if a 9 or (second) $
  542.          --  is encountered.
  543.          --  Also notice the tricky bit with State and Zero_Suppression.
  544.          --  Zero_Suppression is Picture_Error if a '$' or a '9' has been
  545.          --  encountered, exactly the cases where State has been set.
  546.       begin
  547.          Debug_Start ("Leading_Dollar");
  548.          --  Treat as a floating dollar, and unwind otherwise.
  549.          Pic.Floater := '$';
  550.          Pic.Start_Currency := Index;
  551.          Pic.End_Currency := Index;
  552.          Pic.Start_Float := Index;
  553.          Pic.End_Float := Index;
  554.          --  don't increment Pic.Max_Leading_Digits, we need one "real"
  555.          --  currency place.
  556.          Skip; --  known '$'
  557.          loop
  558.             if At_End then return; end if;
  559.             case Look is
  560.                when '_' | '0' | '/' =>
  561.                   Pic.End_Float := Index;
  562.                   Skip;
  563.                when 'B' | 'b'  =>
  564.                   Pic.End_Float := Index;
  565.                   Pic.Picture.Expanded (Index) := 'b';
  566.                   Skip;
  567.                when 'Z' | 'z' =>
  568.                   Pic.Picture.Expanded (Index) := 'Z';
  569.                   --  consistancy
  570.                   if State = Okay then raise Picture_Error;
  571.                   else Zero_Suppression;
  572.                   --  will overwrite Floater and Start_Float
  573.                   end if;
  574.                when '*' =>
  575.                   if State = Okay then raise Picture_Error;
  576.                   else Star_Suppression;
  577.                   --  will overwrite Floater and Start_Float
  578.                   end if;
  579.                when '$' =>
  580.                   Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
  581.                   Pic.End_Float := Index;
  582.                   Pic.End_Currency := Index;
  583.                   Set_State (Okay); Skip;
  584.                when '9' =>
  585.                   if State /= Okay then
  586.                      Pic.Floater := '!';
  587.                      Pic.Start_Float := Invalid_Position;
  588.                      Pic.End_Float := Invalid_Position;
  589.                   end if;
  590.                   --  A single dollar does not a floating make.
  591.                   Number_Completion;
  592.                   return;
  593.                when 'V' | 'v' | '.' =>
  594.                   if State /= Okay then
  595.                      Pic.Floater := '!';
  596.                      Pic.Start_Float := Invalid_Position;
  597.                      Pic.End_Float := Invalid_Position;
  598.                   end if;
  599.                   --  Only one dollar before the sign is okay,
  600.                   --  but doesn't float.
  601.                   Pic.Radix_Position := Index;
  602.                   Skip;
  603.                   Number_Fraction_Or_Dollar;
  604.                   return;
  605.                when others => return;
  606.             end case;
  607.          end loop;
  608.       end Leading_Dollar;
  609.  
  610.       procedure Number_Fraction_Or_Pound is
  611.       begin
  612.          loop
  613.             if At_End then return; end if;
  614.             case Look is
  615.                when '_' | '0' | '/' => Skip;
  616.                when 'B' | 'b'  =>
  617.                   Pic.Picture.Expanded (Index) := 'b';
  618.                   Skip;
  619.                when '#' =>
  620.                   Pic.Max_Trailing_Digits := Pic.Max_Trailing_Digits + 1;
  621.                   Pic.End_Float := Index;
  622.                   Skip;
  623.                   loop
  624.                      if At_End then return; end if;
  625.                      case Look is
  626.                         when '_' | '0' | '/' => Skip;
  627.                         when 'B' | 'b'  =>
  628.                            Pic.Picture.Expanded (Index) := 'b';
  629.                            Skip;
  630.                         when '#' =>
  631.                            Pic.Max_Trailing_Digits :=
  632.                               Pic.Max_Trailing_Digits + 1;
  633.                            Pic.End_Float := Index;
  634.                            Skip;
  635.                         when others => return;
  636.                      end case;
  637.                   end loop;
  638.                when others => Number_Fraction; return;
  639.             end case;
  640.          end loop;
  641.       end Number_Fraction_Or_Pound;
  642.  
  643.       procedure Leading_Pound is
  644.          --  This one is complex!  A Leading_Pound can be fixed or floating,
  645.          --  but in some cases the decision has to be deferred until we leave
  646.          --  this procedure.  Also note that Leading_Pound can be called in
  647.          --  either State.
  648.          --  It will set state to Okay only if a 9 or  (second) # is
  649.          --  encountered.
  650.          --  One Last note :  In ambiguous cases, the currency is treated as
  651.          --  floating unless there is only one '#'.
  652.  
  653.          Inserts : Boolean := False;
  654.          --  set to true if a '_', '0', '/', 'B', or 'b'
  655.          --  is encountered
  656.          Must_Float : Boolean := False;
  657.          --  set to true if a '#' occurs after an
  658.          --  insert.
  659.  
  660.       begin
  661.          Debug_Start ("Leading_Pound");
  662.          Pic.Floater := '#';
  663.          --  Treat as a floating currency.  If it isn't, this will be
  664.          --  overwritten.
  665.          Pic.Start_Currency := Index;
  666.          Pic.End_Currency := Index;
  667.          Pic.Start_Float := Index;
  668.          Pic.End_Float := Index;
  669.          --  don't increment Pic.Max_Leading_Digits, we need one "real"
  670.          --  currency place.
  671.          Pic.Max_Currency_Digits := 1; --  we've seen one.
  672.          Skip; --  known '#'
  673.          loop
  674.             if At_End then return; end if;
  675.             case Look is
  676.                when '_' | '0' | '/' =>
  677.                   Pic.End_Float := Index;
  678.                   Inserts := True;
  679.                   Skip;
  680.                when 'B' | 'b'  =>
  681.                   Pic.Picture.Expanded (Index) := 'b';
  682.                   Pic.End_Float := Index;
  683.                   Inserts := True;
  684.                   Skip;
  685.                when 'Z' | 'z' =>
  686.                   Pic.Picture.Expanded (Index) := 'Z';
  687.                   --  consistancy
  688.                   if Must_Float then raise Picture_Error;
  689.                   else
  690.                      Pic.Max_Leading_Digits := 0;
  691.                      Zero_Suppression;
  692.                      --  will overwrite Floater and Start_Float
  693.                   end if;
  694.                when '*' =>
  695.                   if Must_Float then raise Picture_Error;
  696.                   else
  697.                      Pic.Max_Leading_Digits := 0;
  698.                      Star_Suppression;
  699.                      --  will overwrite Floater and Start_Float
  700.                   end if;
  701.                when '#' =>
  702.                   if Inserts then Must_Float := True; end if;
  703.                   Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
  704.                   Pic.End_Float := Index;
  705.                   Pic.End_Currency := Index;
  706.                   Set_State (Okay);
  707.                   Skip;
  708.                when '9' =>
  709.                   if State /= Okay then
  710.                      Pic.Floater := '!';
  711.                      Pic.Start_Float := Invalid_Position;
  712.                      Pic.End_Float := Invalid_Position;
  713.                      --  a single '#' doesn't float.
  714.                   end if;
  715.                   Number_Completion;
  716.                   return;
  717.                when 'V' | 'v' | '.' =>
  718.                   if State /= Okay then
  719.                      Pic.Floater := '!';
  720.                      Pic.Start_Float := Invalid_Position;
  721.                      Pic.End_Float := Invalid_Position;
  722.                   end if;
  723.                   --  Only one pound before the sign is okay,
  724.                   --  but doesn't float.
  725.                   Pic.Radix_Position := Index;
  726.                   Skip;
  727.                   Number_Fraction_Or_Pound;
  728.                   return;
  729.                when others => return;
  730.             end case;
  731.          end loop;
  732.       end Leading_Pound;
  733.  
  734.       procedure Picture is
  735.          --  Note that Picture can be called in either State.
  736.          --  It will set state to Valid only if a 9 is encountered or floating
  737.          --  currency is called.
  738.       begin
  739.          Debug_Start ("Picture");
  740.          loop
  741.             if At_End then return; end if;
  742.             case Look is
  743.                when '_' | '0' | '/' =>
  744.                   Skip;
  745.                when 'B' | 'b'  =>
  746.                   Pic.Picture.Expanded (Index) := 'b';
  747.                   Skip;
  748.                when '$' => Leading_Dollar; return;
  749.                when '#' => Leading_Pound; return;
  750.                when '9' =>
  751.                   Computed_BWZ := False;
  752.                   Set_State (Okay);
  753.                   Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
  754.                   Skip;
  755.                when 'V' | 'v' | '.' =>
  756.                   Pic.Radix_Position := Index;
  757.                   Skip;
  758.                   Number_Fraction;
  759.                   Trailing_Currency;
  760.                   return;
  761.                when others => return;
  762.             end case;
  763.          end loop;
  764.       end Picture;
  765.  
  766.       procedure Floating_Plus is
  767.       begin
  768.          Debug_Start ("Floating_Plus");
  769.          loop
  770.             if At_End then return; end if;
  771.             case Look is
  772.                when '_' | '0' | '/' =>
  773.                   Pic.End_Float := Index;
  774.                   Skip;
  775.                when 'B' | 'b'  =>
  776.                   Pic.End_Float := Index;
  777.                   Pic.Picture.Expanded (Index) := 'b';
  778.                   Skip;
  779.                when '+' =>
  780.                   Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
  781.                   Pic.End_Float := Index;
  782.                   Skip;
  783.                when '9' =>
  784.                   Number_Completion;
  785.                   return;
  786.                when '.' | 'V' | 'v' =>
  787.                   Pic.Radix_Position := Index;
  788.                   Skip; --  Radix
  789.                   while Is_Insert loop Skip; end loop;
  790.                   if At_End then return; end if;
  791.                   if Look = '+' then
  792.                      loop
  793.                         if At_End then return; end if;
  794.                         case Look is
  795.                            when '+' =>
  796.                               Pic.Max_Trailing_Digits :=
  797.                                  Pic.Max_Trailing_Digits + 1;
  798.                               Pic.End_Float := Index;
  799.                               Skip;
  800.                            when '_' | '0' | '/' =>
  801.                               Skip;
  802.                            when 'B' | 'b'  =>
  803.                               Pic.Picture.Expanded (Index) := 'b';
  804.                               Skip;
  805.                            when others => return;
  806.                         end case;
  807.                      end loop;
  808.                   else Number_Completion;
  809.                   end if;
  810.                   return;
  811.                when others => return;
  812.             end case;
  813.          end loop;
  814.       end Floating_Plus;
  815.  
  816.       procedure Floating_Minus is
  817.       begin
  818.          Debug_Start ("Floating_Minus");
  819.          loop
  820.             if At_End then return; end if;
  821.             case Look is
  822.                when '_' | '0' | '/' =>
  823.                   Pic.End_Float := Index;
  824.                   Skip;
  825.                when 'B' | 'b'  =>
  826.                   Pic.End_Float := Index;
  827.                   Pic.Picture.Expanded (Index) := 'b';
  828.                   Skip;
  829.                when '-' =>
  830.                   Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
  831.                   Pic.End_Float := Index;
  832.                   Skip;
  833.                when '9' =>
  834.                   Number_Completion;
  835.                   return;
  836.                when '.' | 'V' | 'v' =>
  837.                   Pic.Radix_Position := Index;
  838.                   Skip; --  Radix
  839.                   while Is_Insert loop Skip; end loop;
  840.                   if At_End then return; end if;
  841.                   if Look = '-' then
  842.                      loop
  843.                         if At_End then return; end if;
  844.                         case Look is
  845.                            when '-' =>
  846.                               Pic.Max_Trailing_Digits :=
  847.                                  Pic.Max_Trailing_Digits + 1;
  848.                               Pic.End_Float := Index;
  849.                               Skip;
  850.                            when '_' | '0' | '/' =>
  851.                               Skip;
  852.                            when 'B' | 'b'  =>
  853.                               Pic.Picture.Expanded (Index) := 'b';
  854.                               Skip;
  855.                            when others => return;
  856.                         end case;
  857.                      end loop;
  858.                   else Number_Completion;
  859.                   end if;
  860.                   return;
  861.                when others => return;
  862.             end case;
  863.          end loop;
  864.       end Floating_Minus;
  865.  
  866.       procedure Picture_Plus is
  867.       begin
  868.          Debug_Start ("Picture_Plus");
  869.          Pic.Sign_Position := Index;
  870.          --  Treat as a floating sign, and unwind otherwise.
  871.          Pic.Floater := '+';
  872.          Pic.Start_Float := Index;
  873.          Pic.End_Float := Index;
  874.          --  don't increment Pic.Max_Leading_Digits, we need one "real"
  875.          --  sign place.
  876.          Skip; --  Known Plus
  877.          loop
  878.             case Look is
  879.                when '_' | '0' | '/' =>
  880.                   Pic.End_Float := Index;
  881.                   Skip;
  882.                when 'B' | 'b'  =>
  883.                   Pic.End_Float := Index;
  884.                   Pic.Picture.Expanded (Index) := 'b';
  885.                   Skip;
  886.                when '+' =>
  887.                   Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
  888.                   Pic.End_Float := Index;
  889.                   Skip;
  890.                   Set_State (Okay);  --  "++" is enough.
  891.                   Floating_Plus;
  892.                   Trailing_Currency;
  893.                   return;
  894.                when '$' | '#' | '9' | '*' =>
  895.                   if State /= Okay then
  896.                      Pic.Floater := '!';
  897.                      Pic.Start_Float := Invalid_Position;
  898.                      Pic.End_Float := Invalid_Position;
  899.                   end if;
  900.                   Picture;
  901.                   Set_State (Okay);
  902.                   return;
  903.                when '.' | 'V' | 'v' =>
  904.                   if State /= Okay then
  905.                      Pic.Floater := '!';
  906.                      Pic.Start_Float := Invalid_Position;
  907.                      Pic.End_Float := Invalid_Position;
  908.                   end if;
  909.                   Picture;
  910.                   --  don't assume that state is okay, haven't seen a digit.
  911.                   return;
  912.                when others => return;
  913.             end case;
  914.          end loop;
  915.       end Picture_Plus;
  916.  
  917.       procedure Picture_Minus is
  918.       begin
  919.          Debug_Start ("Picture_Minus");
  920.          Pic.Sign_Position := Index;
  921.          --  Treat as a floating sign, and unwind otherwise.
  922.          Pic.Floater := '-';
  923.          Pic.Start_Float := Index;
  924.          Pic.End_Float := Index;
  925.          --  don't increment Pic.Max_Leading_Digits, we need one "real"
  926.          --  sign place.
  927.          Skip; --  Known Minus
  928.          loop
  929.             case Look is
  930.                when '_' | '0' | '/' =>
  931.                   Pic.End_Float := Index;
  932.                   Skip;
  933.                when 'B' | 'b'  =>
  934.                   Pic.End_Float := Index;
  935.                   Pic.Picture.Expanded (Index) := 'b';
  936.                   Skip;
  937.                when '-' =>
  938.                   Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
  939.                   Pic.End_Float := Index;
  940.                   Skip;
  941.                   Set_State (Okay);  --  "-- " is enough.
  942.                   Floating_Minus;
  943.                   Trailing_Currency;
  944.                   return;
  945.                when '$' | '#' | '9' | '*' =>
  946.                   if State /= Okay then
  947.                      Pic.Floater := '!';
  948.                      Pic.Start_Float := Invalid_Position;
  949.                      Pic.End_Float := Invalid_Position;
  950.                   end if;
  951.                   Picture;
  952.                   Set_State (Okay);
  953.                   return;
  954.                when '.' | 'V' | 'v' =>
  955.                   if State /= Okay then
  956.                      Pic.Floater := '!';
  957.                      Pic.Start_Float := Invalid_Position;
  958.                      Pic.End_Float := Invalid_Position;
  959.                   end if;
  960.                   Picture;
  961.                   --  don't assume that state is okay, haven't seen a digit.
  962.                   return;
  963.                when others => return;
  964.             end case;
  965.          end loop;
  966.       end Picture_Minus;
  967.  
  968.       procedure Picture_Bracket is
  969.       begin
  970.          Pic.Sign_Position := Index;
  971.          Debug_Start ("Picture_Bracket");
  972.          Pic.Sign_Position := Index;
  973.          --  Treat as a floating sign, and unwind otherwise.
  974.          Pic.Floater := '<';
  975.          Pic.Start_Float := Index;
  976.          Pic.End_Float := Index;
  977.          --  don't increment Pic.Max_Leading_Digits, we need one "real"
  978.          --  sign place.
  979.          Skip; --  Known Bracket
  980.          loop
  981.             case Look is
  982.                when '_' | '0' | '/' =>
  983.                   Pic.End_Float := Index;
  984.                   Skip;
  985.                when 'B' | 'b'  =>
  986.                   Pic.End_Float := Index;
  987.                   Pic.Picture.Expanded (Index) := 'b';
  988.                   Skip;
  989.                when '<' =>
  990.                   Set_State (Okay);  --  "<<>" is enough.
  991.                   Floating_Bracket;
  992.                   Trailing_Currency;
  993.                   Trailing_Bracket;
  994.                   return;
  995.                when '$' | '#' | '9' | '*' =>
  996.                   if State /= Okay then
  997.                      Pic.Floater := '!';
  998.                      Pic.Start_Float := Invalid_Position;
  999.                      Pic.End_Float := Invalid_Position;
  1000.                   end if;
  1001.                   Picture;
  1002.                   Trailing_Bracket;
  1003.                   Set_State (Okay);
  1004.                   return;
  1005.                when '.' | 'V' | 'v' =>
  1006.                   if State /= Okay then
  1007.                      Pic.Floater := '!';
  1008.                      Pic.Start_Float := Invalid_Position;
  1009.                      Pic.End_Float := Invalid_Position;
  1010.                   end if;
  1011.                   Picture;
  1012.                   --  don't assume that state is okay, haven't seen a digit.
  1013.                   Trailing_Bracket;
  1014.                   return;
  1015.                when others => raise Picture_Error;
  1016.             end case;
  1017.          end loop;
  1018.       end Picture_Bracket;
  1019.  
  1020.       procedure Number is
  1021.       begin
  1022.          Debug_Start ("Number");
  1023.          loop
  1024.             case Look is
  1025.                when '_' | '0' | '/' => Skip;
  1026.                when 'B' | 'b'  =>
  1027.                   Pic.Picture.Expanded (Index) := 'b';
  1028.                   Skip;
  1029.                when '9' =>
  1030.                   Computed_BWZ := False;
  1031.                   Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
  1032.                   Set_State (Okay);
  1033.                   Skip;
  1034.                when '.' | 'V' | 'v' =>
  1035.                   Pic.Radix_Position := Index;
  1036.                   Skip;
  1037.                   Number_Fraction;
  1038.                   return;
  1039.                when others => return;
  1040.             end case;
  1041.             if At_End then return; end if;
  1042.             --  will return in Okay state if a '9' was seen.
  1043.          end loop;
  1044.       end Number;
  1045.  
  1046.       procedure Optional_RHS_Sign is
  1047.       begin
  1048.          Debug_Start ("Optional_RHS_Sign");
  1049.          if At_End then return; end if;
  1050.          case Look is
  1051.             when '+' | '-' =>
  1052.                Pic.Sign_Position := Index;
  1053.                Skip; return;
  1054.             when 'C' | 'c' =>
  1055.                Pic.Sign_Position := Index;
  1056.                Pic.Picture.Expanded (Index) := 'C';
  1057.                Skip;
  1058.                if Look = 'R' or Look = 'r' then
  1059.                   Pic.Second_Sign := Index;
  1060.                   Pic.Picture.Expanded (Index) := 'R';
  1061.                   Skip;
  1062.                else raise Picture_Error;
  1063.                end if;
  1064.                return;
  1065.             when 'D' | 'd' =>
  1066.                Pic.Sign_Position := Index;
  1067.                Pic.Picture.Expanded (Index) := 'D';
  1068.                Skip;
  1069.                if Look = 'B' or Look = 'b' then
  1070.                   Pic.Second_Sign := Index;
  1071.                   Pic.Picture.Expanded (Index) := 'B';
  1072.                   Skip;
  1073.                else raise Picture_Error;
  1074.                end if;
  1075.                return;
  1076.             when others => return;
  1077.          end case;
  1078.       end Optional_RHS_Sign;
  1079.  
  1080.       procedure Picture_String is
  1081.       begin
  1082.          Debug_Start ("Picture_String");
  1083.          while Is_Insert loop Skip; end loop;
  1084.          case Look is
  1085.             when '$' | '#' =>
  1086.                Picture;
  1087.                Optional_RHS_Sign;
  1088.             when '+' => Picture_Plus;
  1089.             when '-' => Picture_Minus;
  1090.             when '<' => Picture_Bracket;
  1091.             when 'Z' | 'z' =>
  1092.                Pic.Picture.Expanded (Index) := 'Z';
  1093.                --  consistancy
  1094.                Zero_Suppression;
  1095.                Trailing_Currency;
  1096.                Optional_RHS_Sign;
  1097.             when '*' =>
  1098.                Star_Suppression;
  1099.                Trailing_Currency;
  1100.                Optional_RHS_Sign;
  1101.             when '9' | '.' | 'V' | 'v' =>
  1102.                Number;
  1103.                Trailing_Currency;
  1104.                Optional_RHS_Sign;
  1105.             when others => raise Picture_Error;
  1106.          end case;
  1107.  
  1108.          Pic.Blank_When_Zero :=  (Computed_BWZ or Pic.Blank_When_Zero) and not
  1109.             Pic.Star_Fill;
  1110.          --  Blank when zero either if the PIC does not contain a '9' or if
  1111.          --  requested by the user and no '*'
  1112.          Pic.Star_Fill := Pic.Star_Fill and Computed_BWZ;
  1113.          --  Star fill if '*' and no '9'.
  1114.          if not At_End then Set_State (Reject); end if;
  1115.  
  1116.       end Picture_String;
  1117.  
  1118.    begin
  1119.  
  1120.       Picture_String;
  1121.  
  1122.       if Debug then
  1123.          Text_IO.New_Line;
  1124.          Text_IO.Put (" Picture : """ &
  1125.                      Pic.Picture.Expanded (1 .. Pic.Picture.Length) & """,");
  1126.          Text_IO.Put (" Floater : '" & Pic.Floater & "',");
  1127.       end if;
  1128.  
  1129.       if State = Reject then raise Picture_Error; end if;
  1130.  
  1131.       Debug_Integer (Pic.Radix_Position, "Radix Positon : ");
  1132.       Debug_Integer (Pic.Sign_Position, "Sign Positon : ");
  1133.       Debug_Integer (Pic.Second_Sign, "Second Sign : ");
  1134.       Debug_Integer (Pic.Start_Float, "Start Float : ");
  1135.       Debug_Integer (Pic.End_Float, "End Float : ");
  1136.       Debug_Integer (Pic.Start_Currency, "Start Currency : ");
  1137.       Debug_Integer (Pic.End_Currency, "End Currency : ");
  1138.       Debug_Integer (Pic.Max_Leading_Digits, "Max Leading Digits : ");
  1139.       Debug_Integer (Pic.Max_Trailing_Digits, "Max Trailing Digits : ");
  1140.       if Debug then Text_IO.New_Line; end if;
  1141.  
  1142.    exception
  1143.       when Constraint_Error => raise Picture_Error;
  1144.       --  to deal with special cases like null strings.
  1145.    end Precalculate;
  1146.  
  1147.  
  1148.    function Format_Number (Pic                 : Format_Record;
  1149.                            Number              : String;
  1150.                            Currency_Symbol     : String;
  1151.                            Fill_Character      : Character;
  1152.                            Separator_Character : Character;
  1153.                            Radix_Point         : Character) return String is
  1154.       --  Changes
  1155.       --  RIE 08/17/94  Fix trailing 9's bug.
  1156.       Attrs         : Number_Attributes := Parse_Number_String (Number);
  1157.       Position      : Integer;
  1158.       Sign_Position : Integer                   := Pic.Sign_Position;
  1159.       --  may float.
  1160.       Answer : String (1 .. Pic.Picture.Length) := Pic.Picture.Expanded;
  1161.       Last          : Integer;
  1162.       Currency_Pos  : Integer := Pic.Start_Currency;
  1163.       Dollar        : Boolean := False;
  1164.       --  overridden immediately if necessary.
  1165.       Zero          : Boolean := True;
  1166.       --  Set to False when a non-zero digit is output.
  1167.    begin
  1168.  
  1169.       if Pic.Start_Currency /= Invalid_Position then
  1170.          Dollar := Answer (Pic.Start_Currency) = '$';
  1171.       end if;
  1172.  
  1173.       --  fix up "direct inserts" outside the playing field.
  1174.       --  Set up as one loop
  1175.       --  to do the beginning, one (reverse) loop to do the end.
  1176.  
  1177.       Last := 1;
  1178.       loop
  1179.          exit when Last = Pic.Start_Float;
  1180.          exit when Last = Pic.Radix_Position;
  1181.          exit when Answer (Last) = '9';
  1182.          case Answer (Last) is
  1183.             when '_' =>
  1184.                Answer (Last) := Separator_Character;
  1185.             when 'b' =>
  1186.                Answer (Last) := ' ';
  1187.             when others =>
  1188.                null;
  1189.          end case;
  1190.          exit when Last = Answer'Last;
  1191.          Last := Last + 1;
  1192.       end loop;
  1193.  
  1194.       --  now for the end...
  1195.       for I in reverse Last .. Answer'Last loop
  1196.          exit when I = Pic.Radix_Position;
  1197.          if Answer (I) = Pic.Floater then
  1198.             exit;
  1199.          end if;
  1200.          --  do this test First, Separator_Character can equal Pic.Floater.
  1201.          case Answer (I) is
  1202.             when '_' =>
  1203.                Answer (I) := Separator_Character;
  1204.             when 'b' =>
  1205.                Answer (I) := ' ';
  1206.             when '9' =>
  1207.                exit;
  1208.             when others =>
  1209.                null;
  1210.          end case;
  1211.       end loop;
  1212.  
  1213.       --  non-floating sign
  1214.  
  1215.       if Pic.Start_Currency /= -1 and then
  1216.          Answer (Pic.Start_Currency) = '#' and then Pic.Floater /= '#' then
  1217.          --  you would think this was a very special case... ;-)
  1218.          if Currency_Symbol'Length >
  1219.             Pic.End_Currency - Pic.Start_Currency + 1 then
  1220.             raise Picture_Error;
  1221.          elsif Currency_Symbol'Length =
  1222.             Pic.End_Currency - Pic.Start_Currency + 1 then
  1223.             Answer (Pic.Start_Currency .. Pic.End_Currency) :=
  1224.                Currency_Symbol;
  1225.          elsif Pic.Radix_Position = Invalid_Position or else
  1226.             Pic.Start_Currency < Pic.Radix_Position then
  1227.                Answer (Pic.Start_Currency .. Pic.End_Currency) :=
  1228.                (others => ' ');
  1229.             Answer (Pic.End_Currency - Currency_Symbol'Length + 1 ..
  1230.                Pic.End_Currency) := Currency_Symbol;
  1231.          else
  1232.             Answer (Pic.Start_Currency .. Pic.End_Currency) :=
  1233.                (others => ' ');
  1234.             Answer (Pic.Start_Currency ..
  1235.                     Pic.Start_Currency + Currency_Symbol'Length - 1) :=
  1236.                Currency_Symbol;
  1237.          end if;
  1238.       end if;
  1239.  
  1240.       --  fill in leading digits
  1241.       if Attrs.End_Of_Int - Attrs.Start_Of_Int + 1 >
  1242.          Pic.Max_Leading_Digits then
  1243.          raise Picture_Error;
  1244.       end if;
  1245.  
  1246.       if Pic.Radix_Position = Invalid_Position then
  1247.          Position := Answer'Last;
  1248.       else
  1249.          Position := Pic.Radix_Position - 1;
  1250.       end if;
  1251.  
  1252.       for I in reverse Attrs.Start_Of_Int .. Attrs.End_Of_Int loop
  1253.          while Answer (Position) /= '9' and Answer (Position) /= Pic.Floater
  1254.          loop
  1255.             if Answer (Position) = '_' then
  1256.                Answer (Position) := Separator_Character;
  1257.             elsif Answer (Position) = 'b' then
  1258.                Answer (Position) := ' ';
  1259.             end if;
  1260.             Position := Position - 1;
  1261.          end loop;
  1262.          Answer (Position) := Number (I);
  1263.          if Number (I) /= '0' then
  1264.             Zero := False;
  1265.          end if;
  1266.          Position := Position - 1;
  1267.       end loop;
  1268.  
  1269.       --  do lead float
  1270.       if Pic.Start_Float = Invalid_Position then
  1271.          --  no leading floats, but need to change '9' to '0', '_' to
  1272.          --  Separator_Character and 'b' to ' '.
  1273.          for I in Last .. Position loop
  1274.             --  Last set when fixing the "uninteresting" leaders above.  Don't
  1275.             --  duplicate the work.
  1276.             if Answer (I) = '9' then
  1277.                Answer (I) := '0';
  1278.             elsif Answer (I) = '_' then
  1279.                Answer (I) := Separator_Character;
  1280.             elsif Answer (I) = 'b' then
  1281.                Answer (I) := ' ';
  1282.             end if;
  1283.          end loop;
  1284.       elsif Pic.Floater = '<' or else Pic.Floater = '+' or else
  1285.          Pic.Floater = '-' then
  1286.             for I in Pic.End_Float .. Position loop --  May be null range.
  1287.                if Answer (I) = '9' then
  1288.                   Answer (I) := '0';
  1289.                elsif Answer (I) = '_' then
  1290.                   Answer (I) := Separator_Character;
  1291.                elsif Answer (I) = 'b' then
  1292.                   Answer (I) := ' ';
  1293.                end if;
  1294.             end loop;
  1295.             if Position > Pic.End_Float then
  1296.                Position := Pic.End_Float;
  1297.             end if;
  1298.             for I in Pic.Start_Float .. Position - 1 loop
  1299.                Answer (I) := ' ';
  1300.             end loop;
  1301.             Answer (Position) := Pic.Floater;
  1302.             Sign_Position     := Position;
  1303.       elsif Pic.Floater = '$' then
  1304.          for I in Pic.End_Float .. Position loop --  May be null range.
  1305.             if Answer (I) = '9' then
  1306.                Answer (I) := '0';
  1307.             elsif Answer (I) = '_' then
  1308.                Answer (I) := Separator_Character;
  1309.             elsif Answer (I) = 'b' then
  1310.                Answer (I) := ' ';
  1311.             end if;
  1312.          end loop;
  1313.          if Position > Pic.End_Float then
  1314.             Position := Pic.End_Float;
  1315.          end if;
  1316.          for I in Pic.Start_Float .. Position - 1 loop
  1317.             Answer (I) := ' ';
  1318.          end loop;
  1319.          Answer (Position) := Pic.Floater;
  1320.          Currency_Pos      := Position;
  1321.       elsif Pic.Floater = '*' then
  1322.          for I in Pic.End_Float .. Position loop --  May be null range.
  1323.             if Answer (I) = '9' then
  1324.                Answer (I) := '0';
  1325.             elsif Answer (I) = '_' then
  1326.                Answer (I) := Separator_Character;
  1327.             elsif Answer (I) = 'b' then
  1328.                Answer (I) := '*';
  1329.             end if;
  1330.          end loop;
  1331.          if Position > Pic.End_Float then
  1332.             Position := Pic.End_Float;
  1333.          end if;
  1334.          for I in Pic.Start_Float .. Position loop
  1335.             Answer (I) := '*';
  1336.          end loop;
  1337.       else
  1338.  
  1339.          if Pic.Floater = '#' then
  1340.             Currency_Pos := Currency_Symbol'Length;
  1341.          end if;
  1342.  
  1343.          for I in reverse Pic.Start_Float .. Position loop
  1344.             case Answer (I) is
  1345.                when '*' =>
  1346.                   Answer (I) := Fill_Character;
  1347.                when 'Z' | 'b' | '/' | '0' =>
  1348.                   Answer (I) := ' ';
  1349.                when '9' =>
  1350.                   Answer (I) := '0';
  1351.                when '.' | 'V' | 'v' | '<' | '$' | '+' | '-' =>
  1352.                   null;
  1353.                when '#' =>
  1354.                   if Currency_Pos = 0 then
  1355.                      Answer (I) := ' ';
  1356.                   else
  1357.                      Answer (I)   := Currency_Symbol (Currency_Pos);
  1358.                      Currency_Pos := Currency_Pos - 1;
  1359.                   end if;
  1360.                when '_' =>
  1361.                   case Pic.Floater is
  1362.                      when '*' =>
  1363.                         Answer (I) := Fill_Character;
  1364.                      when 'Z' | 'b' =>
  1365.                         Answer (I) := ' ';
  1366.                      when '#' =>
  1367.                         if Currency_Pos = 0 then
  1368.                            Answer (I) := ' ';
  1369.                         else
  1370.                            Answer (I)   := Currency_Symbol (Currency_Pos);
  1371.                            Currency_Pos := Currency_Pos - 1;
  1372.                         end if;
  1373.                      when others =>
  1374.                         null;
  1375.                   end case;
  1376.                when others =>
  1377.                   null;
  1378.             end case;
  1379.          end loop;
  1380.  
  1381.          if Pic.Floater = '#' and then Currency_Pos /= 0 then
  1382.             raise Picture_Error;
  1383.          end if;
  1384.  
  1385.       end if;
  1386.  
  1387.       --  do sign
  1388.       if Sign_Position = Invalid_Position then
  1389.          if Attrs.Negative then
  1390.             raise Picture_Error;
  1391.          end if;
  1392.       else
  1393.          if Attrs.Negative then
  1394.             case Answer (Sign_Position) is
  1395.                when 'C' | 'D' | '-' =>
  1396.                   null;
  1397.                when '+' =>
  1398.                   Answer (Sign_Position) := '-';
  1399.                when '<' =>
  1400.                   Answer (Sign_Position)   := '(';
  1401.                   Answer (Pic.Second_Sign) := ')';
  1402.                when others =>
  1403.                   raise Picture_Error;
  1404.             end case;
  1405.          else --  positive
  1406.             case Answer (Sign_Position) is
  1407.                when '-' =>
  1408.                   Answer (Sign_Position) := ' ';
  1409.                when '<' | 'C' | 'D' =>
  1410.                   Answer (Sign_Position)   := ' ';
  1411.                   Answer (Pic.Second_Sign) := ' ';
  1412.                when '+' =>
  1413.                   null;
  1414.                when others =>
  1415.                   raise Picture_Error;
  1416.             end case;
  1417.          end if;
  1418.       end if;
  1419.  
  1420.       --  fill in trailing digits
  1421.       if Pic.Max_Trailing_Digits > 0 then
  1422.          if Attrs.Has_Fraction then
  1423.             Position := Attrs.Start_Of_Fraction;
  1424.             Last     := Pic.Radix_Position + 1;
  1425.             for I in Last .. Answer'Last loop
  1426.                if Answer (I) = '9' or Answer (I) = Pic.Floater then
  1427.                   Answer (I) := Number (Position);
  1428.                   if Number (Position) /= '0' then
  1429.                      Zero := False;
  1430.                   end if;
  1431.                   Position := Position + 1;
  1432.                   Last     := I + 1;
  1433.                   exit when Position > Attrs.End_Of_Fraction;
  1434.                   --  Used up fraction but remember place in Answer
  1435.                elsif Answer (I) = 'b' then
  1436.                   Answer (I) := ' ';
  1437.                elsif Answer (I) = '_' then
  1438.                   Answer (I) := Separator_Character;
  1439.                end if;
  1440.                Last := I + 1;
  1441.             end loop;
  1442.             Position := Last;
  1443.          else
  1444.             Position := Pic.Radix_Position + 1;
  1445.          end if;
  1446.          --  now fill remaining 9's with zeros and _ with separators
  1447.          Last := Answer'Last;
  1448.          for I in Position .. Last loop
  1449.             if Answer (I) = '9' then
  1450.                Answer (I) := '0';
  1451.             elsif Answer (I) = Pic.Floater then
  1452.                Answer (I) := '0';
  1453.             elsif Answer (I) = '_' then
  1454.                Answer (I) := Separator_Character;
  1455.             elsif Answer (I) = 'b' then
  1456.                Answer (I) := ' ';
  1457.             end if;
  1458.          end loop;
  1459.          Position := Last + 1;
  1460.       else
  1461.  
  1462.          if Pic.Floater = '#' and then
  1463.             Currency_Pos <= Currency_Symbol'Length then
  1464.             raise Picture_Error;
  1465.          end if;
  1466.  
  1467.          --  No trailing digits, but now I may need to stick in a currency
  1468.          --  symbol or sign.
  1469.          if Pic.Start_Currency = Invalid_Position then
  1470.             Position := Answer'Last + 1;
  1471.          else
  1472.             Position := Pic.Start_Currency;
  1473.          end if;
  1474.  
  1475.       end if;
  1476.  
  1477.       for I in Position .. Answer'Last loop
  1478.  
  1479.          if Pic.Start_Currency /= Invalid_Position and then
  1480.             Answer (Pic.Start_Currency) = '#' then
  1481.             Currency_Pos := 1;
  1482.          end if;
  1483.  
  1484.          case Answer (I) is
  1485.             when '*' =>
  1486.                Answer (I) := Fill_Character;
  1487.             when 'b' =>
  1488.                Answer (I) := ' ';
  1489.             when '#' =>
  1490.                if Currency_Pos > Currency_Symbol'Length then
  1491.                   Answer (I) := ' ';
  1492.                else
  1493.                   Answer (I)   := Currency_Symbol (Currency_Pos);
  1494.                   Currency_Pos := Currency_Pos + 1;
  1495.                end if;
  1496.             when '_' =>
  1497.                case Pic.Floater is
  1498.                   when '*' =>
  1499.                      Answer (I) := Fill_Character;
  1500.                   when 'Z' | 'z' =>
  1501.                      Answer (I) := ' ';
  1502.                   when '#' =>
  1503.                      if Currency_Pos > Currency_Symbol'Length then
  1504.                         Answer (I) := ' ';
  1505.                      else
  1506.                         Answer (I)   := Currency_Symbol (Currency_Pos);
  1507.                         Currency_Pos := Currency_Pos + 1;
  1508.                      end if;
  1509.                   when others =>
  1510.                      null;
  1511.                end case;
  1512.             when others =>
  1513.                exit;
  1514.          end case;
  1515.       end loop;
  1516.  
  1517.  
  1518.       --  now get rid of Blank_when_Zero and complete Star fill.
  1519.  
  1520.       if Zero and Pic.Blank_When_Zero then --  value is zero, and blank it.
  1521.          Last := Answer'Last;
  1522.  
  1523.          if Dollar then
  1524.             Last := Last - 1 + Currency_Symbol'Length;
  1525.          end if;
  1526.  
  1527.          if Pic.Radix_Position /= Invalid_Position and then
  1528.             Answer (Pic.Radix_Position) = 'V' then
  1529.             Last := Last - 1;
  1530.          end if;
  1531.  
  1532.          return String' (1 .. Last => ' ');
  1533.       elsif Zero and Pic.Star_Fill then
  1534.          Last := Answer'Last;
  1535.  
  1536.          if Dollar then
  1537.             Last := Last - 1 + Currency_Symbol'Length;
  1538.          end if;
  1539.  
  1540.          if Pic.Radix_Position /= Invalid_Position then
  1541.             if Answer (Pic.Radix_Position) = 'V' then
  1542.                Last := Last - 1;
  1543.             elsif Dollar then
  1544.                if Pic.Radix_Position > Pic.Start_Currency then
  1545.                   return String' (1 .. Pic.Radix_Position - 1 => '*') &
  1546.                      Radix_Point &
  1547.                      String' (Pic.Radix_Position + 1 .. Last => '*');
  1548.                else
  1549.                   return
  1550.                      String'
  1551.                      (1 ..
  1552.                       Pic.Radix_Position + Currency_Symbol'Length - 2 =>
  1553.                          '*') & Radix_Point &
  1554.                      String'
  1555.                      (Pic.Radix_Position + Currency_Symbol'Length .. Last
  1556.                       => '*');
  1557.                end if;
  1558.             else
  1559.                return String' (1 .. Pic.Radix_Position - 1 => '*') &
  1560.                   Radix_Point &
  1561.                   String' (Pic.Radix_Position + 1 .. Last => '*');
  1562.             end if;
  1563.          end if;
  1564.          return String' (1 .. Last => '*');
  1565.       end if;
  1566.  
  1567.       --  This was once a simple return statement, now there are nine different
  1568.       --  return cases.  Not to mention the five above to deal with zeros.
  1569.       --  Why no split things out?
  1570.       --  Processing the radix and sign expansion separately
  1571.       --  would require lots of copying--the string and some of its
  1572.       --  indicies--without really simplifying the logic.  The cases are:
  1573.  
  1574.       --  1) Expand $, replace '.' with Radix_Point
  1575.       --  2) No currency expansion, replace '.' with Radix_Point
  1576.       --  3) Expand $, radix blanked
  1577.       --  4) No currency expansion, radix blanked
  1578.       --  5) Elide V
  1579.       --  6) Expand $, Elide V
  1580.       --  7) Elide V, Expand $ (Two cases depending on order.)
  1581.       --  8) No radix, expand $
  1582.       --  9) No radix, no currency expansion
  1583.  
  1584.       if Pic.Radix_Position /= Invalid_Position then
  1585.          if Answer (Pic.Radix_Position) = '.' then
  1586.             Answer (Pic.Radix_Position) := Radix_Point;
  1587.             if Dollar then
  1588.                return Answer (1 .. Currency_Pos - 1) & Currency_Symbol &
  1589.                   Answer (Currency_Pos + 1 .. Answer'Last);
  1590.                --  1) Expand $, replace '.' with Radix_Point
  1591.             else
  1592.                return Answer;
  1593.                --  2) No currency expansion, replace '.' with Radix_Point
  1594.             end if;
  1595.          elsif Answer (Pic.Radix_Position) = ' ' then --  blanked radix.
  1596.             if Dollar then
  1597.                return Answer (1 .. Currency_Pos - 1) & Currency_Symbol &
  1598.                   Answer (Currency_Pos + 1 .. Answer'Last);
  1599.                --  3) Expand $, radix blanked
  1600.             else
  1601.                return Answer;
  1602.                --  4) No expansion, radix blanked
  1603.             end if;
  1604.          else --  V cases...
  1605.             if not Dollar then
  1606.                return Answer (1 .. Pic.Radix_Position - 1) &
  1607.                   Answer (Pic.Radix_Position + 1 .. Answer'Last);
  1608.                --  5) Elide V
  1609.             elsif Currency_Pos < Pic.Radix_Position then
  1610.                return Answer (1 .. Currency_Pos - 1) & Currency_Symbol &
  1611.                   Answer (Currency_Pos + 1 .. Pic.Radix_Position - 1) &
  1612.                   Answer (Pic.Radix_Position + 1 .. Answer'Last);
  1613.                --  6) Expand $, Elide V
  1614.             else
  1615.                return Answer (1 .. Pic.Radix_Position - 1) &
  1616.                   Answer (Pic.Radix_Position + 1 .. Currency_Pos - 1) &
  1617.                   Currency_Symbol &
  1618.                   Answer (Currency_Pos + 1 .. Answer'Last);
  1619.                --  7) Elide V, Expand $
  1620.             end if;
  1621.          end if;
  1622.       elsif Dollar then
  1623.          return Answer (1 .. Currency_Pos - 1) & Currency_Symbol &
  1624.             Answer (Currency_Pos + 1 .. Answer'Last);
  1625.          --  8) No radix, expand $
  1626.       else
  1627.          return Answer;
  1628.          --  9) No radix, no currency expansion
  1629.       end if;
  1630.  
  1631.    end Format_Number;
  1632.  
  1633.    function Expand (Picture : in String) return String is
  1634.       Result : String (1 .. MAX_PICSIZE);
  1635.       Picture_Index : Integer := Picture'First;
  1636.       Result_Index : Integer := Result'First;
  1637.       Count : Natural;
  1638.       Last : Integer;
  1639.       package Int_IO is new Text_IO.Integer_IO (Integer);
  1640.    begin
  1641.       if Picture'Length < 1 then raise Picture_Error; end if;
  1642.       if Picture (Picture'First) = '(' then raise Picture_Error; end if;
  1643.  
  1644.       loop
  1645.          case Picture (Picture_Index) is
  1646.             when '(' =>
  1647.                Int_IO.Get (Picture (Picture_Index + 1 .. Picture'Last),
  1648.                            Count, Last);
  1649.                if Picture (Last + 1) /= ')' then raise Picture_Error; end if;
  1650.                --  In what follows note that one copy of the repeated
  1651.                --  character has already been made, so a count of one is a
  1652.                --  no-op, and a count of zero erases a character.
  1653.                for I in 2 .. Count loop
  1654.                   Result (Result_Index + I - 2) := Picture (Picture_Index - 1);
  1655.                end loop;
  1656.                Result_Index := Result_Index + Count - 1;
  1657.                Picture_Index := Last + 2;
  1658.                --  Last + 1 was a ')' throw it away too.
  1659.             when ')' => raise Picture_Error;
  1660.             when others =>
  1661.                Result (Result_Index) := Picture (Picture_Index);
  1662.                Picture_Index := Picture_Index + 1;
  1663.                Result_Index := Result_Index + 1;
  1664.          end case;
  1665.          exit when Picture_Index > Picture'Last;
  1666.       end loop;
  1667.       return Result (1 .. Result_Index - 1);
  1668.    exception
  1669.       when others => raise Picture_Error;
  1670.    end Expand;
  1671.  
  1672.    package Strings renames Ada.Strings;
  1673.    package Strings_Fixed renames Ada.Strings.Fixed;
  1674.    package Text_IO renames Ada.Text_IO;
  1675.  
  1676.    function Valid
  1677.      (Pic_String      : in String;
  1678.       Blank_When_Zero : in Boolean := False)
  1679.       return            Boolean is
  1680.    begin
  1681.       declare
  1682.          Expanded_Pic : constant String := Expand (Pic_String);
  1683.          --  Raises Picture_Error if Item not well-formed
  1684.       begin
  1685.          return not Blank_When_Zero or
  1686.             Strings_Fixed.Index (Expanded_Pic, "*") = 0;
  1687.          --  False only if Blank_When_0 is True but the pic string
  1688.          --  has a '*'
  1689.       end;
  1690.    exception
  1691.       when others =>
  1692.          return False;
  1693.    end Valid;
  1694.  
  1695.    function To_Picture
  1696.      (Pic_String      : in String;
  1697.       Blank_When_Zero : in Boolean := False)
  1698.       return            Picture is
  1699.       Result : Picture;
  1700.    begin
  1701.       declare
  1702.          Item : constant String := Expand (Pic_String);
  1703.       begin
  1704.          Result.Contents.Picture         := (Item'Length, Item);
  1705.          Result.Contents.Blank_When_Zero := Blank_When_Zero;
  1706.          Precalculate (Result.Contents);
  1707.          return Result;
  1708.       end;
  1709.    exception
  1710.       when others =>
  1711.          raise Picture_Error;
  1712.    end To_Picture;
  1713.  
  1714.    function Pic_String (Pic : in Picture) return String is
  1715.    begin
  1716.       return Pic.Contents.Picture.Expanded;
  1717.    end Pic_String;
  1718.  
  1719.    function Blank_When_Zero (Pic : in Picture) return Boolean is
  1720.    begin
  1721.       return Pic.Contents.Blank_When_Zero;
  1722.    end Blank_When_Zero;
  1723.  
  1724.    package body Decimal_Output is
  1725.  
  1726.       function Length (Pic      : in Picture;
  1727.                        Currency : in String := Default_Currency)
  1728.       return Natural is
  1729.          Picstr     : constant String := Pic_String (Pic);
  1730.          V_Adjust   : Integer := 0;
  1731.          Cur_Adjust : Integer := 0;
  1732.       begin
  1733.          --  Check if Picstr has 'V' or '$'
  1734.          --   If 'V', then length is 1 less than otherwise
  1735.          --   If '$', then length is Currency'Length-1 more than otherwise
  1736.          --  <<TBD>> This should use the string handling package
  1737.          for I in Picstr'Range loop
  1738.             if Picstr (I) = 'V' then
  1739.                V_Adjust := -1;
  1740.             elsif Picstr (I) = '$' then
  1741.                Cur_Adjust := Currency'Length - 1;
  1742.             end if;
  1743.          end loop;
  1744.          return Picstr'Length - V_Adjust + Cur_Adjust;
  1745.       end Length;
  1746.  
  1747.       --  Valid doesn't use at all Item ???
  1748.       function Valid (Item     : Num;
  1749.                       Pic      : in Picture;
  1750.                       Currency : in String := Default_Currency)
  1751.       return Boolean is
  1752.          Start_Currency : constant Integer := Pic.Contents.Start_Currency;
  1753.          End_Currency   : constant Integer := Pic.Contents.End_Currency;
  1754.       begin
  1755.          if Start_Currency = Invalid_Position then
  1756.             --  no currency symbol in pic string, hence pic OK
  1757.             return True;
  1758.          elsif Pic.Contents.Picture.Expanded (Start_Currency) = '#'
  1759.            and Currency'Length > End_Currency - Start_Currency + 1 then
  1760.             return False;
  1761.          else
  1762.             return True;
  1763.          end if;
  1764.       end Valid;
  1765.  
  1766.       function Image (Item       : in Num;
  1767.                       Pic        : in Picture;
  1768.                       Currency   : in String    := Default_Currency;
  1769.                       Fill       : in Character := Default_Fill;
  1770.                       Separator  : in Character := Default_Separator;
  1771.                       Radix_Mark : in Character := Default_Radix_Mark)
  1772.       return String is
  1773.       begin
  1774.          return Format_Number
  1775.             (Pic.Contents, Num'Image (Item),
  1776.              Currency, Fill, Separator, Radix_Mark);
  1777.       end Image;
  1778.  
  1779.       procedure Put (File       : in Text_IO.File_Type;
  1780.                      Item       : in Num;
  1781.                      Pic        : in Picture;
  1782.                      Currency   : in String    := Default_Currency;
  1783.                      Fill       : in Character := Default_Fill;
  1784.                      Separator  : in Character := Default_Separator;
  1785.                      Radix_Mark : in Character := Default_Radix_Mark) is
  1786.       begin
  1787.          Text_IO.Put (File, Image (Item, Pic,
  1788.                                    Currency, Fill, Separator, Radix_Mark));
  1789.       end Put;
  1790.  
  1791.       procedure Put (Item       : in Num;
  1792.                      Pic        : in Picture;
  1793.                      Currency   : in String    := Default_Currency;
  1794.                      Fill       : in Character := Default_Fill;
  1795.                      Separator  : in Character := Default_Separator;
  1796.                      Radix_Mark : in Character := Default_Radix_Mark) is
  1797.       begin
  1798.          Text_IO.Put (Image (Item, Pic,
  1799.                              Currency, Fill, Separator, Radix_Mark));
  1800.       end Put;
  1801.  
  1802.       procedure Put (To         : out String;
  1803.                      Item       : in Num;
  1804.                      Pic        : in Picture;
  1805.                      Currency   : in String    := Default_Currency;
  1806.                      Fill       : in Character := Default_Fill;
  1807.                      Separator  : in Character := Default_Separator;
  1808.                      Radix_Mark : in Character := Default_Radix_Mark) is
  1809.          Result : constant String :=
  1810.            Image (Item, Pic, Currency, Fill, Separator, Radix_Mark);
  1811.       begin
  1812.          if Result'Length > To'Length then
  1813.             raise Text_IO.Layout_Error;
  1814.          else
  1815.             Strings_Fixed.Move (Source => Result, Target => To,
  1816.                                 Justify => Strings.Right);
  1817.          end if;
  1818.       end Put;
  1819.  
  1820.    end Decimal_Output;
  1821.  
  1822. end Ada.Text_IO.Editing;
  1823.